# -*- coding: UTF-8 -*-
# 高阶函数: 把函数作为参数传入，这样的函数称为高阶函数，函数式编程就是指这种高度抽象的编程范式
def test1():
    # 变量可以指向函数
    x = abs(-10)
    print(x)
    # 函数名也是变量，指向一个可以计算绝对值的函数
    f = abs
    print(f(-100))
    # 传入函数: 既然变量可以指向函数，函数的参数能接收变量，那么一个函数就可以接收另一个函数作为参数，这种函数就称之为高阶函数。
    print(add(-5,6,abs))
    
def add(x,y,f):
    return f(x)+f(y)

from functools import reduce
def testMapReduce():
    print("\n------testMapReduce------\n")
    # map: 函数接收两个参数，一个是函数，一个是Iterable，map将传入的函数依次作用到序列的每个元素，并把结果作为新的Iterator返回
    print("map--------------------")
    for x in map(f,range(1,10)):
        print(x)
    # reduce: 把一个函数作用在一个序列[x1, x2, x3, ...]上，这个函数必须接收两个参数，reduce把结果继续和序列的下一个元素做累积计算
    print("reduce--------------------")
    print(reduce(fn,[1,3,5,7,9]))

def fn(x,y):
    return x*10+y

def f(x):
    return x*x

# 利用map()函数，把用户输入的不规范的英文名字，变为首字母大写，其他小写的规范名字。输入：['adam', 'LISA', 'barT']，输出：['Adam', 'Lisa', 'Bart']
def normalize(name):
    return name[0].upper()+name[1:].lower()

def ext1():
    print("\n------ext1-----\n")
    for x in map(normalize,['adam','LISA','barT']):
        print(x)

# Python提供的sum()函数可以接受一个list并求和，请编写一个prod()函数，可以接受一个list并利用reduce()求积：
def ext2():
    print("\n------ext2-----\n")
    print(prod([3,5,7,9]))
def prod(L):
    return reduce(chenji,L);
def chenji(x,y):
    return x*y

# filter: Python内建的filter()函数用于过滤序列, filter()把传入的函数依次作用于每个元素，然后根据返回值是True还是False决定保留还是丢弃该元素
def testFilter():
    print("\n------testFilter-----\n")
    # 在一个list中，删掉偶数，只保留奇数
    for x in filter(is_odd,[1,2,4,5,6,9,10,15]):
        print(x)
    # 把一个序列中的空字符串删掉
    for x in filter(not_empty,['A','','B',None,'C','  ']):
        print(x)

def is_odd(n):
    return n%2==1
def not_empty(s):
    return s and s.strip()

# sorted: 排序算法
def testSorted():
    print("\n------testSorted-----\n")
    # [-21, -12, 5, 9, 36]
    sorted([36,5,-12,9,-21])
    # sorted()函数也是一个高阶函数，它还可以接收一个key函数来实现自定义的排序，例如按绝对值大小排序
    # [5, 9, -12, -21, 36]
    sorted([36, 5, -12, 9, -21], key=abs)
    # sorted传入key函数，即可实现忽略大小写的排序
    # ['about', 'bob', 'Credit', 'Zoo']
    sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
    # 进行反向排序，不必改动key函数，可以传入第三个参数reverse=True
    # ['Zoo', 'Credit', 'bob', 'about']
    sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)

# L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def ext3():
    L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
    print("请用sorted()对上述列表分别按名字排序")
    for x in sorted(L,key=by_name):
        print(x[0],x[1])
    print("请用sorted()对上述列表分别按成绩从高到低排序")
    for x in sorted(L,key=by_score,reverse=True):
        print(x[0],x[1])

def by_name(t):
    return t[0].lower()

def by_score(t):
    return t[1]


if __name__ == '__main__':
    test1()
    testMapReduce()
    ext1()
    ext2()
    testFilter()
    testSorted()
    ext3()